package com.zf.mall.gateway.filters;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import com.alibaba.fastjson.JSON;
import com.zf.mall.common.response.ErrorEnum;
import com.zf.mall.common.response.ResponseResultModel;
import com.zf.mall.common.util.CacheConstants;
import com.zf.mall.gateway.config.IgnoreUrlConfig;
import com.zf.mall.gateway.util.URLTool;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

@Slf4j
@Component
public class AuthFilter implements GlobalFilter, Ordered {

	@Autowired
	IgnoreUrlConfig ignoreUrlConfig;

	@Resource(name = "stringRedisTemplate")
    private ValueOperations<String, String> sops;
	
	@Override
	public int getOrder() {
		return -100;
	}

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		String _url = exchange.getRequest().getURI().getPath();
		//log.info("开始进行统一鉴权................................{}",_url);
		// 过滤白名单
		if (URLTool.matches(_url, ignoreUrlConfig.getWhite())) {
			return chain.filter(exchange);
		}

		String requestMethodName = exchange.getRequest().getMethod().name();
		if("GET".equals(requestMethodName.toUpperCase())) {
			return chain.filter(exchange);
		}
		
		// 过滤黑名单
		if (URLTool.matches(_url, ignoreUrlConfig.getBlack())) {
			return setUnauthorizedResponse(exchange, ErrorEnum.C22007);
		}

		
		String token = getUserToken(exchange.getRequest());
		//log.info("鉴权请求TOKEN: ................................{}",token);
		if (StrUtil.isBlank(token)) {
			return setUnauthorizedResponse(exchange, ErrorEnum.C22008);
		}

		String userId = sops.get(CacheConstants.USER_LOGIN_KEY + token);
		if (StrUtil.isBlank(userId)) {
			return setUnauthorizedResponse(exchange, ErrorEnum.C22009);
		}

		exchange.getRequest().getHeaders().add("userId", userId);
		return chain.filter(exchange);
	}

	
	
	/**辅助方法**/
	private String getUserToken(ServerHttpRequest request) {
		return request.getHeaders().getFirst(CacheConstants.USER_TOKEN);
	}

	private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange, ErrorEnum e) {
		ServerHttpResponse response = exchange.getResponse();
		response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
		response.setStatusCode(HttpStatus.OK);
		
		//log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
		
		return response.writeWith(Mono.fromSupplier(() -> {
			DataBufferFactory bufferFactory = response.bufferFactory();
			return bufferFactory.wrap(JSON.toJSONBytes(new ResponseResultModel<>(e)));
		}));
	}
	
	
	private String getTokenKey(String token) {
		return CacheConstants.USER_LOGIN_KEY + token;
	}

}
